home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / compress / gnucpio.zip / MAIN.C < prev    next >
C/C++ Source or Header  |  1996-01-01  |  14KB  |  526 lines

  1. /* main.c - main program and argument processing for cpio.
  2.    Copyright (C) 1990, 1991, 1992 Free Software Foundation, Inc.
  3.  
  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 2, or (at your option)
  7.    any later version.
  8.  
  9.    This program is distributed in the hope that it will be useful,
  10.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.    GNU General Public License for more details.
  13.  
  14.    You should have received a copy of the GNU General Public License
  15.    along with this program; if not, write to the Free Software
  16.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /* Written by Phil Nelson <phil@cs.wwu.edu>,
  19.    David MacKenzie <djm@gnu.ai.mit.edu>,
  20.    and John Oleynick <juo@klinzhai.rutgers.edu>.  */
  21.  
  22. #include <stdio.h>
  23. #include <getopt.h>
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include "filetypes.h"
  27. #include "system.h"
  28. #include "cpiohdr.h"
  29. #include "dstring.h"
  30. #include "extern.h"
  31. #include "rmt.h"
  32.  
  33. struct option long_opts[] =
  34. {
  35.   {"null", 0, 0, '0'},
  36.   {"append", 0, 0, 'A'},
  37.   {"block-size", 1, 0, 130},
  38.   {"create", 0, 0, 'o'},
  39.   {"dereference", 0, 0, 'L'},
  40.   {"dot", 0, 0, 'V'},
  41.   {"extract", 0, 0, 'i'},
  42.   {"file", 1, 0, 'F'},
  43.   {"force-local", 0, &f_force_local, 1},
  44.   {"format", 1, 0, 'H'},
  45.   {"help", 0, 0, 132},
  46.   {"io-size", 1, 0, 'C'},
  47.   {"link", 0, &link_flag, TRUE},
  48.   {"list", 0, &table_flag, TRUE},
  49.   {"make-directories", 0, &create_dir_flag, TRUE},
  50.   {"message", 1, 0, 'M'},
  51.   {"no-absolute-filenames", 0, 0, 136},
  52.   {"no-preserve-owner", 0, 0, 134},
  53.   {"nonmatching", 0, ©_matching_files, FALSE},
  54.   {"numeric-uid-gid", 0, &numeric_uid, TRUE},
  55.   {"only-verify-crc", 0, 0, 139},
  56.   {"owner", 1, 0, 'R'},
  57.   {"pass-through", 0, 0, 'p'},
  58.   {"pattern-file", 1, 0, 'E'},
  59.   {"preserve-modification-time", 0, &retain_time_flag, TRUE},
  60.   {"rename", 0, &rename_flag, TRUE},
  61.   {"rename-batch-file", 1, 0, 137},
  62.   {"quiet", 0, 0, 138},
  63.   {"sparse", 0, 0, 135},
  64.   {"swap", 0, 0, 'b'},
  65.   {"swap-bytes", 0, 0, 's'},
  66.   {"swap-halfwords", 0, 0, 'S'},
  67.   {"reset-access-time", 0, &reset_time_flag, TRUE},
  68.   {"unconditional", 0, &unconditional_flag, TRUE},
  69.   {"verbose", 0, &verbose_flag, TRUE},
  70.   {"version", 0, 0, 131},
  71. #ifdef DEBUG_CPIO
  72.   {"debug", 0, &debug_flag, TRUE},
  73. #endif
  74.   {0, 0, 0, 0}
  75. };
  76.  
  77. /*  Print usage message and exit with error.  */
  78.  
  79. void
  80. usage (fp, status)
  81.   FILE *fp;
  82.   int status;
  83. {
  84. #ifdef __MSDOS__
  85.   extern char *version_string;
  86.   fprintf(stderr, "\nGNU cpio %s\n", version_string);
  87. #endif
  88.   fprintf (fp, "\
  89. Usage: %s {-o|--create} [-0acvABLV] [-C bytes] [-H format] [-M message]\n\
  90.        [-O [[user@]host:]archive] [-F [[user@]host:]archive]\n\
  91.        [--file=[[user@]host:]archive] [--format=format] [--message=message]\n\
  92.        [--null] [--reset-access-time] [--verbose] [--dot] [--append]\n\
  93.        [--block-size=blocks] [--dereference] [--io-size=bytes] [--quiet]\n\
  94.        [--force-local] [--help] [--version] < name-list [> archive]\n", program_name);
  95.   fprintf (fp, "\n\
  96.        %s {-i|--extract} [-bcdfmnrtsuvBSV] [-C bytes] [-E file] [-H format]\n\
  97.        [-M message] [-R [user][:.][group]] [-I [[user@]host:]archive]\n\
  98.        [-F [[user@]host:]archive] [--file=[[user@]host:]archive]\n\
  99.        [--make-directories] [--nonmatching] [--preserve-modification-time]\n\
  100.        [--numeric-uid-gid] [--rename] [--list] [--swap-bytes] [--swap] [--dot]\n\
  101.        [--unconditional] [--verbose] [--block-size=blocks] [--swap-halfwords]\n\
  102.        [--io-size=bytes] [--pattern-file=file] [--format=format]\n\
  103.        [--owner=[user][:.][group]] [--no-preserve-owner] [--message=message]\n\
  104.        [--force-local] [--no-absolute-filenames] [--sparse] [--only-verify-crc]\n\
  105.        [--quiet] [--help] [--version] [pattern...] [< archive]\n",
  106.        program_name);
  107.   fprintf (fp, "\n\
  108.        %s {-p|--pass-through} [-0adlmuvLV] [-R [user][:.][group]]\n\
  109.        [--null] [--reset-access-time] [--make-directories] [--link] [--quiet]\n\
  110.        [--preserve-modification-time] [--unconditional] [--verbose] [--dot]\n\
  111.        [--dereference] [--owner=[user][:.][group]] [--no-preserve-owner]\n\
  112.        [--sparse] [--help] [--version] destination-directory < name-list\n", program_name);
  113.   exit (status);
  114. }
  115.  
  116. /* Process the arguments.  Set all options and set up the copy pass
  117.    directory or the copy in patterns.  */
  118.  
  119. void
  120. process_args (argc, argv)
  121.      int argc;
  122.      char *argv[];
  123. {
  124.   extern char *version_string;
  125.   void (*copy_in) ();        /* Work around for pcc bug.  */
  126.   void (*copy_out) ();
  127.   int c;
  128.   char *input_archive_name = 0;
  129.   char *output_archive_name = 0;
  130.  
  131.   if (argc < 2)
  132.     usage (stderr, 2);
  133.  
  134.   xstat = lstat;
  135.  
  136.   while ((c = getopt_long (argc, argv,
  137.                "0aAbBcC:dfE:F:H:iI:lLmM:noO:prR:sStuvVz",
  138.                long_opts, (int *) 0)) != -1)
  139.     {
  140.       switch (c)
  141.     {
  142.     case 0:            /* A long option that just sets a flag.  */
  143.       break;
  144.  
  145.     case '0':        /* Read null-terminated filenames.  */
  146.       name_end = '\0';
  147.       break;
  148.  
  149.     case 'a':        /* Reset access times.  */
  150.       reset_time_flag = TRUE;
  151.       break;
  152.  
  153.     case 'A':        /* Append to the archive.  */
  154.       append_flag = TRUE;
  155.       break;
  156.  
  157.     case 'b':        /* Swap bytes and halfwords.  */
  158.       swap_bytes_flag = TRUE;
  159.       swap_halfwords_flag = TRUE;
  160.       break;
  161.  
  162.     case 'B':        /* Set block size to 5120.  */
  163.       io_block_size = 5120;
  164.       break;
  165.  
  166.     case 130:        /* --block-size */
  167.       io_block_size = atoi (optarg);
  168.       if (io_block_size < 1)
  169.         error (2, 0, "invalid block size");
  170.       io_block_size *= 512;
  171.       break;
  172.  
  173.     case 'c':        /* Use the old portable ASCII format.  */
  174.       if (archive_format != arf_unknown)
  175.         usage (stderr, 2);
  176. #ifdef SVR4_COMPAT
  177.       archive_format = arf_newascii; /* -H newc.  */
  178. #else
  179.       archive_format = arf_oldascii; /* -H odc.  */
  180. #endif
  181.       break;
  182.  
  183.     case 'C':        /* Block size.  */
  184.       io_block_size = atoi (optarg);
  185.       if (io_block_size < 1)
  186.         error (2, 0, "invalid block size");
  187.       break;
  188.  
  189.     case 'd':        /* Create directories where needed.  */
  190.       create_dir_flag = TRUE;
  191.       break;
  192.  
  193.     case 'f':        /* Only copy files not matching patterns.  */
  194.       copy_matching_files = FALSE;
  195.       break;
  196.  
  197.     case 'E':        /* Pattern file name.  */
  198.       pattern_file_name = optarg;
  199.       break;
  200.  
  201.     case 'F':        /* Archive file name.  */
  202.       archive_name = optarg;
  203.       break;
  204.  
  205.     case 'H':        /* Header format name.  */
  206.       if (archive_format != arf_unknown)
  207.         usage (stderr, 2);
  208.       if (!strcmp (optarg, "crc") || !strcmp (optarg, "CRC"))
  209.         archive_format = arf_crcascii;
  210.       else if (!strcmp (optarg, "newc") || !strcmp (optarg, "NEWC"))
  211.         archive_format = arf_newascii;
  212.       else if (!strcmp (optarg, "odc") || !strcmp (optarg, "ODC"))
  213.         archive_format = arf_oldascii;
  214.       else if (!strcmp (optarg, "bin") || !strcmp (optarg, "BIN"))
  215.         archive_format = arf_binary;
  216.       else if (!strcmp (optarg, "ustar") || !strcmp (optarg, "USTAR"))
  217.         archive_format = arf_ustar;
  218.       else if (!strcmp (optarg, "tar") || !strcmp (optarg, "TAR"))
  219.         archive_format = arf_tar;
  220.       else if (!strcmp (optarg, "hpodc") || !strcmp (optarg, "HPODC"))
  221.         archive_format = arf_hpoldascii;
  222.       else if (!strcmp (optarg, "hpbin") || !strcmp (optarg, "HPBIN"))
  223.         archive_format = arf_hpbinary;
  224.       else
  225.         error (2, 0, "\
  226. invalid archive format `%s'; valid formats are:\n\
  227. crc newc odc bin ustar tar (all-caps also recognized)", optarg);
  228.       break;
  229.  
  230.     case 'i':        /* Copy-in mode.  */
  231.       if (copy_function != 0)
  232.         usage (stderr, 2);
  233.       copy_function = process_copy_in;
  234.       break;
  235.  
  236.     case 'I':        /* Input archive file name.  */
  237.       input_archive_name = optarg;
  238.       break;
  239.  
  240.     case 'k':        /* Handle corrupted archives.  We always handle
  241.                    corrupted archives, but recognize this
  242.                    option for compatability.  */
  243.       break;
  244.  
  245.     case 'l':        /* Link files when possible.  */
  246.       link_flag = TRUE;
  247.       break;
  248.  
  249.     case 'L':        /* Dereference symbolic links.  */
  250.       xstat = stat;
  251.       break;
  252.  
  253.     case 'm':        /* Retain previous file modify times.  */
  254.       retain_time_flag = TRUE;
  255.       break;
  256.  
  257.     case 'M':        /* New media message.  */
  258.       set_new_media_message (optarg);
  259.       break;
  260.  
  261.     case 'n':        /* Long list owner and group as numbers.  */
  262.       numeric_uid = TRUE;
  263.       break;
  264.  
  265.     case 136:        /* --no-absolute-filenames */
  266.       no_abs_paths_flag = TRUE;
  267.       break;
  268.     
  269.     case 134:        /* --no-preserve-owner */
  270.       if (set_owner_flag || set_group_flag)
  271.         usage (stderr, 2);
  272.       no_chown_flag = TRUE;
  273.       break;
  274.  
  275.     case 'o':        /* Copy-out mode.  */
  276.       if (copy_function != 0)
  277.         usage (stderr, 2);
  278.       copy_function = process_copy_out;
  279.       break;
  280.  
  281.     case 'O':        /* Output archive file name.  */
  282.       output_archive_name = optarg;
  283.       break;
  284.  
  285.     case 139:
  286.       only_verify_crc_flag = TRUE;
  287.       break;
  288.  
  289.     case 'p':        /* Copy-pass mode.  */
  290.       if (copy_function != 0)
  291.         usage (stderr, 2);
  292.       copy_function = process_copy_pass;
  293.       break;
  294.  
  295.     case 'r':        /* Interactively rename.  */
  296.       rename_flag = TRUE;
  297.       break;
  298.  
  299.     case 137:
  300.       rename_batch_file = optarg;
  301.       break;
  302.  
  303.     case 138:
  304.       quiet_flag = TRUE;
  305.       break;
  306.  
  307.     case 'R':        /* Set the owner.  */
  308.       if (no_chown_flag)
  309.         usage (stderr, 2);
  310. #ifndef __MSDOS__
  311.       {
  312.         char *e, *u, *g;
  313.  
  314.         e = parse_user_spec (optarg, &set_owner, &set_group, &u, &g);
  315.         if (e)
  316.           error (2, 0, "%s: %s", optarg, e);
  317.         if (u)
  318.           {
  319.         free (u);
  320.         set_owner_flag = TRUE;
  321.           }
  322.         if (g)
  323.           {
  324.         free (g);
  325.         set_group_flag = TRUE;
  326.           }
  327.       }
  328. #endif
  329.       break;
  330.  
  331.     case 's':        /* Swap bytes.  */
  332.       swap_bytes_flag = TRUE;
  333.       break;
  334.  
  335.     case 'S':        /* Swap halfwords.  */
  336.       swap_halfwords_flag = TRUE;
  337.       break;
  338.  
  339.     case 't':        /* Only print a list.  */
  340.       table_flag = TRUE;
  341.       break;
  342.  
  343.     case 'u':        /* Replace all!  Unconditionally!  */
  344.       unconditional_flag = TRUE;
  345.       break;
  346.  
  347.     case 'v':        /* Verbose!  */
  348.       verbose_flag = TRUE;
  349.       break;
  350.  
  351.     case 'V':        /* Print `.' for each file.  */
  352.       dot_flag = TRUE;
  353.       break;
  354.  
  355.     case 131:
  356.       printf ("GNU cpio %s", version_string);
  357.       exit (0);
  358.       break;
  359.  
  360.     case 135:
  361.       sparse_flag = TRUE;
  362.       break;
  363.  
  364.     case 132:        /* --help */
  365.       usage (stdout, 0);
  366.       break;
  367.  
  368.     default:
  369.       usage (stderr, 2);
  370.     }
  371.     }
  372.  
  373.   /* Do error checking and look at other args.  */
  374.  
  375.   if (copy_function == 0)
  376.     {
  377.       if (table_flag)
  378.     copy_function = process_copy_in;
  379.       else
  380.     usage (stderr, 2);
  381.     }
  382.  
  383.   if ((!table_flag || !verbose_flag) && numeric_uid)
  384.     usage (stderr, 2);
  385.  
  386.   /* Work around for pcc bug.  */
  387.   copy_in = process_copy_in;
  388.   copy_out = process_copy_out;
  389.  
  390.   if (copy_function == copy_in)
  391.     {
  392.       archive_des = 0;
  393.       if (link_flag || reset_time_flag || xstat != lstat || append_flag
  394.       || sparse_flag
  395.       || output_archive_name
  396.       || (archive_name && input_archive_name))
  397.     usage (stderr, 2);
  398.       if (archive_format == arf_crcascii)
  399.     crc_i_flag = TRUE;
  400.       num_patterns = argc - optind;
  401.       save_patterns = &argv[optind];
  402.       if (input_archive_name)
  403.     archive_name = input_archive_name;
  404.     }
  405.   else if (copy_function == copy_out)
  406.     {
  407.       archive_des = 1;
  408.       if (argc != optind || create_dir_flag || rename_flag
  409.       || table_flag || unconditional_flag || link_flag
  410.       || retain_time_flag || no_chown_flag || set_owner_flag
  411.       || set_group_flag || swap_bytes_flag || swap_halfwords_flag
  412.       || (append_flag && !(archive_name || output_archive_name))
  413.       || rename_batch_file || no_abs_paths_flag
  414.       || input_archive_name || (archive_name && output_archive_name))
  415.     usage (stderr, 2);
  416.       if (archive_format == arf_unknown)
  417.     archive_format = arf_binary;
  418.       if (output_archive_name)
  419.     archive_name = output_archive_name;
  420.     }
  421.   else
  422.     {
  423.       /* Copy pass.  */
  424.       archive_des = -1;
  425.       if (argc - 1 != optind || archive_format != arf_unknown
  426.       || swap_bytes_flag || swap_halfwords_flag
  427.       || table_flag || rename_flag || append_flag
  428.       || rename_batch_file || no_abs_paths_flag)
  429.     usage (stderr, 2);
  430.       directory_name = argv[optind];
  431.     }
  432.  
  433.   if (archive_name)
  434.     {
  435.       if (copy_function != copy_in && copy_function != copy_out)
  436.     usage (stderr, 2);
  437.       archive_des = open_archive (archive_name);
  438.       if (archive_des < 0)
  439.     error (1, errno, "%s", archive_name);
  440.     }
  441.  
  442. #ifndef __MSDOS__
  443.   /* Prevent SysV non-root users from giving away files inadvertantly.
  444.      This happens automatically on BSD, where only root can give
  445.      away files.  */
  446.   if (set_owner_flag == FALSE && set_group_flag == FALSE && geteuid ())
  447.     no_chown_flag = TRUE;
  448. #endif
  449. }
  450.  
  451. /* Initialize the input and output buffers to their proper size and
  452.    initialize all variables associated with the input and output
  453.    buffers.  */
  454.  
  455. void
  456. initialize_buffers ()
  457. {
  458.   int in_buf_size, out_buf_size;
  459.  
  460.   if (copy_function == process_copy_in)
  461.     {
  462.       /* Make sure the input buffer can always hold 2 blocks and that it
  463.      is big enough to hold 1 tar record (512 bytes) even if it
  464.      is not aligned on a block boundary.  The extra buffer space
  465.      is needed by process_copyin and peek_in_buf to automatically
  466.      figure out what kind of archive it is reading.  */
  467.       if (io_block_size >= 512)
  468.     in_buf_size = 2 * io_block_size;
  469.       else
  470.     in_buf_size = 1024;
  471.       out_buf_size = DISK_IO_BLOCK_SIZE;
  472.     }
  473.   else if (copy_function == process_copy_out)
  474.     {
  475.       in_buf_size = DISK_IO_BLOCK_SIZE;
  476.       out_buf_size = io_block_size;
  477.     }
  478.   else
  479.     {
  480.       in_buf_size = DISK_IO_BLOCK_SIZE;
  481.       out_buf_size = DISK_IO_BLOCK_SIZE;
  482.     }
  483.  
  484.   input_buffer = (char *) xmalloc (in_buf_size);
  485.   in_buff = input_buffer;
  486.   input_buffer_size = in_buf_size;
  487.   input_size = 0;
  488.   input_bytes = 0;
  489.  
  490.   output_buffer = (char *) xmalloc (out_buf_size);
  491.   out_buff = output_buffer;
  492.   output_size = 0;
  493.   output_bytes = 0;
  494.  
  495.   /* Clear the block of zeros.  */
  496.   bzero (zeros_512, 512);
  497. }
  498.  
  499. void
  500. main (argc, argv)
  501.      int argc;
  502.      char *argv[];
  503. {
  504.   program_name = argv[0];
  505.   umask (0);
  506.  
  507. #ifdef __TURBOC__
  508.   _fmode = O_BINARY;        /* Put stdin and stdout in binary mode.  */
  509. #endif
  510. #ifdef __EMX__            /* gcc on OS/2.  */
  511.   _response (&argc, &argv);
  512.   _wildcard (&argc, &argv);
  513. #endif
  514.  
  515.   process_args (argc, argv);
  516.  
  517.   initialize_buffers ();
  518.  
  519.   (*copy_function) ();
  520.  
  521.   if (archive_des >= 0 && rmtclose (archive_des) == -1)
  522.     error (1, errno, "error closing archive");
  523.  
  524.   exit (0);
  525. }
  526.